// type svgPathCommand = {
//     commandType: string,
//     params: Array<Pos | number>
// }

/**
 * svg path 功能库类
 * */
export class SvgPath {
    /**
     * 构造函数
     *
     * @param { Object } [oriPos = { x: 0, y: 0 }] - 绘制点起始坐标
     * */
    constructor(oriPos = { x: 0, y: 0 }) {
        this.addPathCommand({
            commandType: 'M',
            params: [oriPos]
        });
    }

    /**
     * svgPathCommandArr - svg path 命令对象组
     * */
    svgPathCommandArr = [];

    /**
     * 获取当前 svg path 字符串
     *
     * @return { string } svg path 字符串
     * */
    getSvgPath = () => {
        let svgPathStr = '';

        /**
         * 获取 svg path params 字符串
         * */
        const getParamsStr = function (params) {
            let reStr = '';
            const isNumberReg = new RegExp(/^[+-]?\d*(\.\d*)?(e[+-]?\d+)?$/);

            // 生成 params 字符串
            params.forEach((paramItem) => {
                if (reStr !== '') {
                    reStr += ' ';
                }

                reStr += isNumberReg.test(paramItem)
                    // 是 number
                    ? `${ paramItem }`
                    // 是 Pos
                    : `${ paramItem.x },${ paramItem.y }`;
            });

            return reStr;
        }

        // 生成 svg path 字符串
        this.svgPathCommandArr.forEach((pathCommandItem) => {
            if (svgPathStr !== '') {
                svgPathStr += ' ';
            }

            svgPathStr += `${ pathCommandItem.commandType } ${ getParamsStr(pathCommandItem.params) }`;
        });

        return svgPathStr;
    }

    /**
     * checkPathCommand - 校验 svg 命令是否合法
     *
     * @param { Object } pathCommand - svg path 命令
     * @return { boolean } 传入 svg path 命令是否合法
     * */
    checkPathCommand = (pathCommand) => {
        // todo 校验 pathCommand 是否合法

        return true;
    }

    /**
     * addPathCommand - 添加 svg path 命令
     *
     * @param { Object } pathCommand - svg path 命令字符串
     * @return { boolean } 是否添加成功
     * */
    addPathCommand = (pathCommand) => {
        if (!this.checkPathCommand(pathCommand)) {
            return false;
        }

        // 添加命令对象
        this.svgPathCommandArr.push(pathCommand);
        return true;
    }

    /**
     * splicePathCommand - 删除或更改 svg path 命令
     *
     * @param { number } index - 命令索引
     * @param { Object } newPathCommand - 需更替的新 svg path 命令
     * @return { Object | undefined } 被删除的 svg path 命令对象, 若传入 index 不存在则返回 undefined
     * */
    splicePathCommand = (index, newPathCommand) => {
        if (this.svgPathCommandArr.length <= index) {
            return void 0;
        }

        return newPathCommand
            ? this.svgPathCommandArr.splice(index, 1)[0]
            : this.svgPathCommandArr.splice(index, 1, newPathCommand)[0];
    }

    /**
     * moveTo - 绘制点移动
     *
     * @param { Object } pos - 指定点坐标
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    moveTo = (pos, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 'm' : 'M',
            params: [pos]
        });
    }

    /**
     * lineTo - 从 当前绘制点 向 目标绘制点 画一条线段
     *
     * @param { Object } pos - 指定点坐标
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    lineTo = (pos, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 'l' : 'L',
            params: [pos]
        });
    }

    /**
     * horizontalLineTo - 当前绘制点 沿 X轴 移动指定值并沿着路径画一条线段
     *
     * @param { number } x - x 轴坐标值
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    horizontalLineTo = (x, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 'h' : 'H',
            params: [x]
        });
    }

    /**
     * verticalLineTo - 当前绘制点 沿 Y轴 移动指定值并沿着路径画一条线段
     *
     * @param { number } y - y 轴坐标值
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    verticalLineTo = (y, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 'v' : 'V',
            params: [y]
        });
    }

    /**
     * curveTo - 三次贝塞尔曲线, 基于 当前绘制点, 起点控制点, 终点控制点, 目标绘制点 绘制曲线
     *
     * @param { Object } beginPos - 起点控制点
     * @param { Object } endPos - 终点控制点
     * @param { Object } targetPos - 目标绘制点
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    curveTo = (beginPos, endPos, targetPos, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 'c' : 'C',
            params: [beginPos, endPos, targetPos]
        });
    }

    /**
     * smoothCurveTo - 三次贝塞尔曲线, 基于 当前绘制点, 终点控制点, 目标绘制点 绘制曲线
     *
     * @param { Object } endPos - 终点控制点
     * @param { Object } targetPos - 目标绘制点
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    smoothCurveTo = (endPos, targetPos, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 's' : 'S',
            params: [endPos, targetPos]
        });
    }

    /**
     * quadraticCurveTo - 二次贝塞尔曲线, 基于 当前绘制点, 控制点, 目标绘制点 绘制曲线
     *
     * @param { Object } pos - 控制点
     * @param { Object } targetPos - 目标绘制点
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    quadraticCurveTo = (pos, targetPos, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 'q' : 'Q',
            params: [pos, targetPos]
        });
    }

    /**
     * smoothQuadraticCurveTo - 二次贝塞尔曲线, 基于 当前绘制点, 目标绘制点 绘制曲线
     *
     * @param { Object } targetPos - 目标绘制点
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    smoothQuadraticCurveTo = (targetPos, isRelative = false) => {
        this.addPathCommand({
            commandType: isRelative ? 't' : 'T',
            params: [targetPos]
        });
    }

    /**
     * arc - 绘制椭圆曲线, 并跳转到目标绘制点
     *
     * @param { number } radiusX - 椭圆 X 轴向半径
     * @param { number } radiusY - 椭圆 Y 轴向半径
     * @param { number } angle - 椭圆相对 X 轴旋转角度
     * @param { boolean } isLargeArc - true 为绘制弧度更大的弧线, false 为绘制更小的弧线
     * @param { boolean } isClockwise - true 表示基于椭圆焦点 X 轴向顺时针绘制弧线, false 表示基于椭圆焦点 X 轴向逆时针绘制弧线
     * @param { Object } targetPos - 目标绘制点
     * @param { boolean } [isRelative = false] - 是基于当前绘制点的相对定位
     * */
    arc = (
        radiusX,
        radiusY,
        angle,
        isLargeArc,
        isClockwise,
        targetPos,
        isRelative = false
    ) => {
        this.addPathCommand({
            commandType: isRelative ? 'a' : 'A',
            params: [
                radiusX,
                radiusY,
                angle,
                isLargeArc ? 1 : 0,
                isClockwise ? 1 : 0,
                targetPos
            ]
        });
    }

    /**
     * closeCurrentPath - 闭合当前路径
     *
     * @todo 去验证下这个命令后能不能继续跟其它命令并且是否会变更绘制点位置
     * */
    closeCurrentPath = () => {
        this.addPathCommand({
            commandType: 'z',
            params: []
        });
    }
}

export default {
    SvgPath
}